package form;

import form.exception.*;
import java.util.ArrayList;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession; // Sessions are required for request.getParameter()

/**
 * Class used to create and validate forms.
 * It has some limitations regarding to field types and
 * parameter values, but the most important ones are covered.
 *
 * Current Limitations to forms is that you cant change the type
 * on the fly - except for set a Custom Field Type - and clear it.
 * Once created it's bound to a type. This should support should be
 * added later, though.
 * 
 * @author Simon Zimmermann
 * @version 1.0
 * @since 24.10.2009
 */
public class Form {

    protected HttpServletRequest request;
    private boolean isBound;
    private ArrayList<FormField> fieldsList;
    private FieldTypes fieldTypes;

    /**
     * Unbound form. Doesnt have a purpose at the moment.
     * The point is that this could be used to create a form without
     * writing the HTML. 
     */
    protected Form() {
        this.fieldTypes = new FieldTypes();
        this.fieldsList = new ArrayList<FormField>();
        this.isBound = false;
    }

    /**
     * Bound state of a HttpServletRequest object. Currently
     * only meaningful way of creating a form.
     * @param request
     */
    public Form(HttpServletRequest request) {
        this.request = request;
        this.fieldTypes = new FieldTypes();
        this.fieldsList = new ArrayList<FormField>();
        this.isBound = true;
    }

    /**
     * Checks to see if the Entire Form is valid.
     * Should add some error reporting here. Maybe a list of errors.
     * @return
     */
    public boolean isValid() {
        boolean valid = true;
        for (FormField formField : getFieldsList()) {
            if(!formField.isFieldValid())
                valid = false;
        }
        return valid;
    }

    /**
     * Creates a new field if the type is correct.
     * @param name
     * @param type enum type with a string
     * @throws FieldTypeNotFoundException
     */
    public FormField newField(String name, String type)
            throws FieldTypeNotFoundException, FieldNotFoundException {
        if (fieldTypes.isFieldType(type)) {
            fieldsList.add(new FormField(name, fieldTypes.getFieldType(type)));
            setFieldValue(name); // if Field isn't correctly set, it will be set to null.
            return getFormField(name);
        } else {
            throw new FieldTypeNotFoundException("Field type you specified does not exist.");
        }
    }

    /**
     * Returns the value of a field or thows an exceptions.
     * @param name of field.
     * @return String containing the value of a Field.
     * @throws FieldNotFoundException
     */
    public String getFieldValue(String name) throws FieldNotFoundException {
        if ((getFormField(name)) != null) {
            if (getFormField(name).getFieldValue() != null) {
                return getFormField(name).getFieldValue();
            } else {
                return "Empty Field!";
            }
        }
        throw new FieldNotFoundException("The Parameter field you are looking for does not exist.");
    }

    /**
     * Set the value of a Field.
     * @param name
     * @param value
     */
    private void setFieldValue(String name) {
        String fieldValue = request.getParameter(name);
        if (fieldValue != null) {
            getFormField(name).setFieldValue(fieldValue);
        } else {
            getFormField(name).setFieldValue(null);
        }
    }

    /**
     * Return a formfield in the Form. 
     * @param name
     * @return
     */
    private FormField getFormField(String name) {
        for (FormField formField : getFieldsList()) {
            if (formField.getName().toLowerCase().equals(name.toLowerCase())) {
                return formField;
            }
        }
        return null;
    }

    // Getters & Setters.
    public HttpServletRequest getRequest() {
        return request;
    }

    public boolean getIsBound() {
        return isBound;
    }

    public ArrayList<FormField> getFieldsList() {
        return fieldsList;
    }
}
